
package rv32isc

import chisel3._
import chisel3.util._

import config.Configs._
import utils.OP_TYPES._
import utils.LS_TYPES._
import utils._

import chisel3.util.experimental.loadMemoryFromFile


import firrtl.annotations.MemoryLoadFileType


class MemUnifiedIO extends Bundle {
    val instAddr = Input(UInt(ADDR_WIDTH.W))  // 指令地址
    val inst = Output(UInt(INST_WIDTH.W))     // 指令输出

    val dataAddr = Input(UInt(ADDR_WIDTH.W))  // 数据地址
    val dataIn = Input(UInt(DATA_WIDTH.W))    // 数据写入
    val dataOut = Output(UInt(DATA_WIDTH.W))  // 数据读取

    val bundleMemDataControl = new BundleMemDataControl()  // 数据控制信号
}

class MemUnified(memTest: Boolean = false) extends Module {
    val io = IO(new MemUnifiedIO()) // 输入输出接口

    // 合并指令内存和数据内存
    val mem = Mem(MEM_INST_SIZE + MEM_DATA_SIZE, UInt(INST_WIDTH.W)) 

    // 加载指令内存
    if (memTest) {
        loadMemoryFromFile(
            mem,
            "src/test/scala/rv32isc/randMemInst.hex",
            MemoryLoadFileType.Hex
        )
    } else {
        loadMemoryFromFile(
            mem,
            "src/test/scala/rv32isc/MemInst.hex",
            MemoryLoadFileType.Hex
        )
    }

    // 读取指令内存
    io.inst := mem.read(io.instAddr >> INST_BYTE_WIDTH_LOG.U)

    // 使用寄存器来存储数据和结果，避免组合逻辑环路
    val dataLoad = WireDefault(0.U(DATA_WIDTH.W))  // 使用寄存器来保存加载的内存数据
    val result = WireDefault(0.U(DATA_WIDTH.W))    // 使用寄存器保存结果

    // 数据加载：此操作需要在时钟上同步
    when(io.dataAddr >= MEM_INST_SIZE.U) {  // 判断是否是数据内存区域
        //val adjustedDataAddr = io.dataAddr //- MEM_INST_SIZE.U
        dataLoad := mem.read(io.dataAddr >> DATA_BYTE_WIDTH_LOG.U)
    }

    // STORE指令
    when(io.bundleMemDataControl.ctrlStore) {
        //io.dataOut := io.dataAddr
        when(io.bundleMemDataControl.ctrlLSType === LS_W) { // 修改全部4字节
            mem.write(io.dataAddr >> DATA_BYTE_WIDTH_LOG.U, io.dataIn)
        }.elsewhen(io.bundleMemDataControl.ctrlLSType === LS_H) {   // 修改低2字节
            mem.write(io.dataAddr >> DATA_BYTE_WIDTH_LOG.U, Cat(dataLoad(31, 16), io.dataIn(15, 0)))
        }.otherwise {   // 修改最低一个字节
            mem.write(io.dataAddr >> DATA_BYTE_WIDTH_LOG.U, Cat(dataLoad(31, 8), io.dataIn(7, 0)))
        }
    }

    // LOAD指令
    when (io.bundleMemDataControl.ctrlLoad) {
        when(io.bundleMemDataControl.ctrlLSType === LS_W) {
            result := dataLoad
        }.elsewhen(io.bundleMemDataControl.ctrlLSType === LS_H) {
            when (io.bundleMemDataControl.ctrlSigned) {
                result := Cat(Fill(16, dataLoad(15)), dataLoad(15, 0))
            } .otherwise {
                result := Cat(Fill(16, 0.U), dataLoad(15, 0))
            }
        }.otherwise {
            when (io.bundleMemDataControl.ctrlSigned) {
                result := Cat(Fill(24, dataLoad(7)), dataLoad(7, 0))
            } .otherwise {
                result := Cat(Fill(24, 0.U), dataLoad(7, 0))
            }
        }
    } .otherwise {
        result := io.dataAddr // 非LOAD指令时返回地址
    }

    // 输出
    io.dataOut := result
}
